float2 mouseCoords;
float2 textureSize;

float value;
float range; 

#define NUM_WEIGHTS 9

float weights[NUM_WEIGHTS] =
{
	0.01,
	0.1,
	0.14,
	0.16,
	0.18,
	0.16,
	0.14,
	0.1,
	0.01,
};

float kernel[NUM_WEIGHTS] =
{
	-4,
	-3,
	-2,
	-1,
	0,
	1, 
	2,
	3,
	4,
};

sampler2D tex : register(s0);

struct VertexShaderInput
{
    float4 Position : POSITION0;
	float2 uv		: TEXCOORD;
};

struct VertexShaderOutput
{
    float4 Position : POSITION0;
	float2 uv		: TEXCOORD;
};

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
    VertexShaderOutput output;
	output.Position = input.Position;
	output.uv = input.uv;

    return output;
}

float4 normal_ps(VertexShaderOutput input) : COLOR0
{
	return tex2D(tex, input.uv);
}

float4 renderValue_ps(float2 uv : TEXCOORD) : COLOR0
{
	float2 location = float2(uv.x * textureSize.x, uv.y * textureSize.y);
		float dist = saturate(distance(location, mouseCoords) / range);

	float v = (value * (1 - dist));

	return float4(1.f, 1.f, 1.f, v);
}

float4 renderCircle_ps(VertexShaderOutput input) : COLOR0
{
	return float4(0, 1, 0, 1);
}

float4 renderBlur_ps(VertexShaderOutput input, uniform float2 step) : COLOR0
{
	float2 location = float2(input.uv.x * textureSize.x, input.uv.y * textureSize.y);
	float dist = saturate(distance(location, mouseCoords) / range);

	float v = 0.f;
	float2 scr_uv = input.uv * textureSize;
	// blur across the x-axis
	for (int i = 0; i < NUM_WEIGHTS; i++)
	{
		float2 uv = (scr_uv + float2(kernel[i], kernel[i]) * step) / textureSize;
		v += tex2D(tex, uv).a * weights[i];
	}
	
	return float4(1.f, 1.f, 1.f, v);// lerp(current, v, 1.f - dist));
}


float4 renderNormal_ps(float2 uv : TEXCOORD) : COLOR0
{
	float x = 5.f / textureSize.x;
	float y = 5.f / textureSize.y;
	float2 up = float2(0.f, -y);
		float2 left = float2(-x, 0);
		float2 right = float2(x, 0);
		float2 down = float2(0.f, y);

		float2 sample1 = uv + up + left;
		float2 sample2 = uv + up + right;
		float2 sample3 = uv + down + left;
		float2 sample4 = uv + down + right;

		float3 p1 = float3(sample1.x * textureSize.x, 0.f, sample1.y * textureSize.y);
		float3 p2 = float3(sample2.x * textureSize.x, 0.f, sample2.y * textureSize.y);
		float3 p3 = float3(sample3.x * textureSize.x, 0.f, sample3.y * textureSize.y);
		float3 p4 = float3(sample4.x * textureSize.x, 0.f, sample4.y * textureSize.y);


		p1.y = tex2D(tex, sample1).a		* range;
		p2.y = tex2D(tex, sample2).a		* range;
		p3.y = tex2D(tex, sample3).a		* range;
		p4.y = tex2D(tex, sample4).a	* range;



		float3 Ta_1 = normalize(p2 - p1);
		float3 Ta_2 = normalize(p3 - p1);

		float3 Tb_1 = normalize(p1 - p4);
		float3 Tb_2 = normalize(p3 - p4);

		float3 n1 = (cross(Ta_2, Ta_1));
		float3 n2 = (cross(Tb_2, Tb_1));

		return float4(normalize((n1) * .5f), 1.f);
}

technique normal
{
    pass Pass1
    {
        // TODO: set renderstates here.

        VertexShader = compile vs_2_0 VertexShaderFunction();
        PixelShader = compile ps_2_0 normal_ps();
    }
}

technique renderValue
{
	pass p1
	{
		VertexShader = compile vs_2_0 VertexShaderFunction();
		PixelShader = compile ps_2_0 renderValue_ps();
	}
}

technique renderCircle
{
	pass p1
	{
		VertexShader = compile vs_2_0 VertexShaderFunction();
		PixelShader = compile ps_2_0 renderCircle_ps();
	}
}

technique renderBlur
{
	pass p1
	{
		VertexShader = compile vs_3_0 VertexShaderFunction();
		PixelShader = compile ps_3_0 renderBlur_ps(float2(1, 0));
	}

	pass p2
	{
		VertexShader = compile vs_3_0 VertexShaderFunction();
		PixelShader = compile ps_3_0 renderBlur_ps(float2(0, 1));
	}
}

technique renderNormals
{
	pass p0
	{
		VertexShader = compile vs_3_0 VertexShaderFunction();
		PixelShader = compile ps_3_0 renderNormal_ps();
	}
}
